/*
 * Copyright 2012 The Netty Project
 *
 * The Netty Project licenses this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
package com.iot.ic.tcp.netty;

import com.iot.ic.model.Device;
import com.iot.ic.service.DeviceService;
import com.iot.ic.tcp.CustomDispatcher;
import com.iot.ic.tcp.model.MsgRequest;
import com.iot.ic.tcp.model.MsgResponse;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelId;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleStateEvent;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 通过心跳机制实现延迟断开tcp链接
 * @author xiuge
 * 2016年12月21日上午9:10:54
 */
@Sharable//要么就是加上注解@Sharable，要么就是每次都new一个新的handler的实例
@Component
public class CustomHandler extends ChannelInboundHandlerAdapter {
    private Logger logger= LoggerFactory.getLogger(CustomHandler.class);
	
    @Autowired
	private CustomDispatcher customDispatcher;
    
    @Autowired
   	private DeviceService deviceService;
    
    public static Map<String,ChannelHandlerContext> channelMap=new HashMap<>();
    
    public static  Map<ChannelId,String> deviceNosMap=new HashMap<>();

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    	MsgRequest request = (MsgRequest) msg;
		MsgResponse response= customDispatcher.dispatch(request);
		if (response==null) {
            response=new MsgResponse();
			/*ctx.close();
			return;*/
		}
		if (request.getDeviceNo() != null) {
			deviceNosMap.put(ctx.channel().id(), request.getDeviceNo());
		}
		ChannelFuture future=ctx.writeAndFlush(response);
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        // IdleStateHandler 所产生的 IdleStateEvent 的处理逻辑.
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent e = (IdleStateEvent) evt;
            switch (e.state()) {
                case READER_IDLE:
                    handleReaderIdle(ctx);
                    break;
                case WRITER_IDLE:
                    handleWriterIdle(ctx);
                    break;
                case ALL_IDLE:
                    handleAllIdle(ctx);
                    break;
                default:
                    break;
            }
        }
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
    	//channelMap.put("test", ctx);
    	logger.warn("---" + ctx.channel().remoteAddress() + "建立链接");
        super.channelActive(ctx);
        MsgResponse response= new MsgResponse();
        ctx.writeAndFlush(response);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
    	logger.warn( ctx.channel().remoteAddress() + "链接关闭");
        ctx.close();
        //channelMap.remove("test");
		super.channelInactive(ctx);
		String deviceNo = deviceNosMap.get(ctx.channel().id());
		if (deviceNo != null) {
			Device device = new Device();
			deviceService.updateDeviceStateByDeviceNo(deviceNo);
			deviceNosMap.remove(ctx.channel().id());
		}
		
    }

    protected void handleReaderIdle(ChannelHandlerContext ctx) {
    	logger.warn("---READER_IDLE---");
    }

    protected void handleWriterIdle(ChannelHandlerContext ctx) {
    	logger.warn("---WRITER_IDLE---");
    }

    protected void handleAllIdle(ChannelHandlerContext ctx) {
    	logger.warn("---ALL_IDLE---");
    	logger.warn("---超时10s----");
        ctx.close();
    }
    
    @Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
		ctx.flush();
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		cause.printStackTrace();
		ctx.close();// 发生异常，关闭链路
		logger.error("---" + ctx.channel().remoteAddress() + " 发生异常");
		super.exceptionCaught(ctx, cause);
	}
	
    
    
}